package com.slofzx.nuoda.evaluation.project.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.slofzx.nuoda.common.dto.PageDTO;
import com.slofzx.nuoda.common.exception.ServiceException;
import com.slofzx.nuoda.common.util.IdGen;
import com.slofzx.nuoda.evaluation.project.enums.AdjustRatioEnum;
import com.slofzx.nuoda.evaluation.project.dao.ProjectInfoDAO;
import com.slofzx.nuoda.evaluation.project.dto.ProjectInfoDTO;
import com.slofzx.nuoda.evaluation.project.dto.ProjectYearDataExcelDTO;
import com.slofzx.nuoda.evaluation.project.entity.ProjectInfo;
import com.slofzx.nuoda.evaluation.project.entity.ProjectYearData;
import com.slofzx.nuoda.evaluation.project.dto.ProjectYearDataDTO;
import com.slofzx.nuoda.evaluation.project.vo.ProjectYearDataVO;
import com.slofzx.nuoda.evaluation.project.dao.ProjectYearDataDAO;
import com.slofzx.nuoda.evaluation.project.service.ProjectYearDataService;
import com.slofzx.nuoda.common.enums.CommonResultEnum;
import com.slofzx.nuoda.common.enums.ServiceResult;
import com.slofzx.nuoda.common.service.impl.BaseServiceImpl;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 项目年度数据服务实现类
 *
 * @author nuoda
 * @since 2023-10-20 15:57:42
 */
@Service("projectYearDataService")
public class ProjectYearDataServiceImpl extends BaseServiceImpl implements ProjectYearDataService {
    private static final String YEAR_STR = "year";
    private static final Double DEFAULT_RATIO = 1D;
    @Resource
    private ProjectYearDataDAO projectYearDataDAO;
    @Resource
    private ProjectInfoDAO projectInfoDAO;

    protected ProjectYearDataVO parseEntity2VO(ProjectYearData entity) {
        ProjectYearDataVO vo = new ProjectYearDataVO();
        vo.setId(entity.getId());
        vo.setProjectId(entity.getProjectId());
        vo.setBatchId(entity.getBatchId());
        vo.setYear(entity.getYear());
        vo.setProductionRate(entity.getProductionRate());
        vo.setWaterInjection(entity.getWaterInjection());
        vo.setSteamInjection(entity.getSteamInjection());
        vo.setLiquidOutput(entity.getLiquidOutput());
        vo.setOilOutput(entity.getOilOutput());
        vo.setGasOutput(entity.getGasOutput());
        vo.setCondensateOutput(entity.getCondensateOutput());
        vo.setLiquidGasOutput(entity.getLiquidGasOutput());
        vo.setDrugCost(entity.getDrugCost());
        vo.setCreateUser(entity.getCreateUser());
        vo.setCreateTime(entity.getCreateTime());
        vo.setCostRatio(entity.getCostRatio());
        vo.setInvestRatio(entity.getInvestRatio());
        vo.setOutputRatio(entity.getOutputRatio());
        vo.setSumInvest(entity.getSumInvest());
        vo.setDrillExtractInvest(entity.getDrillExtractInvest());
        vo.setGroundInvest(entity.getGroundInvest());
        vo.setOtherInvest(entity.getOtherInvest());
        vo.setOutputWellOpenCount(entity.getOutputWellOpenCount());
        vo.setInjectionWellOpenCount(entity.getInjectionWellOpenCount());
        vo.setFixedPerson(entity.getFixedPerson());
        return vo;
    }

    protected ProjectYearData parseDTO2Entity(ProjectYearDataDTO dto) {
        ProjectYearData entity = new ProjectYearData();
        entity.setId(dto.getId());
        entity.setProjectId(dto.getProjectId());
        entity.setBatchId(dto.getBatchId());
        entity.setProductionRate(dto.getProductionRate());
        entity.setWaterInjection(dto.getWaterInjection());
        entity.setSteamInjection(dto.getSteamInjection());
        entity.setLiquidOutput(dto.getLiquidOutput());
        entity.setOilOutput(dto.getOilOutput());
        entity.setGasOutput(dto.getGasOutput());
        entity.setCondensateOutput(dto.getCondensateOutput());
        entity.setLiquidGasOutput(dto.getLiquidGasOutput());
        entity.setYear(dto.getYear());
        entity.setDrugCost(dto.getDrugCost());
        entity.setSumInvest(dto.getSumInvest());
        entity.setDrillExtractInvest(dto.getDrillExtractInvest());
        entity.setGroundInvest(dto.getGroundInvest());
        entity.setOtherInvest(dto.getOtherInvest());
        entity.setOutputWellOpenCount(dto.getOutputWellOpenCount());
        entity.setInjectionWellOpenCount(dto.getInjectionWellOpenCount());
        entity.setFixedPerson(dto.getFixedPerson());
        return entity;
    }

    @Override
    public ProjectYearDataVO queryById(String id) {
        ProjectYearData entity = this.projectYearDataDAO.selectById(id);
        if (entity == null) {
            return null;
        }
        return parseEntity2VO(entity);
    }

    @Override
    public List<ProjectYearDataVO> queryList(ProjectYearDataDTO dto) {
        //mybatis-plus 写法示例
        //IPage<ProjectYearData> pageResult = this.evaModelDAO.selectPage(new Page<>(dto.getPageNo(),dto.getPageSize()),null);
        //List<ProjectYearData> dataList = pageResult.getRecords();
        //dto.setCount((int) pageResult.getTotal());
        List<ProjectYearData> dataList = this.projectYearDataDAO.queryList(dto);
        if (null == dataList || dataList.isEmpty()) {
            return Collections.emptyList();
        }
        List<ProjectYearDataVO> resultList = new ArrayList(dataList.size());
        for (ProjectYearData item : dataList) {
            ProjectYearDataVO vo = parseEntity2VO(item);
            resultList.add(vo);
        }
        // TODO 添加其他关联查询数据
        return resultList;
    }

    @Override
    public ServiceResult create(ProjectYearDataDTO dto) {
        // TODO 添加校验逻辑
        ProjectYearData entity = parseDTO2Entity(dto);
        preInsert(entity);
        this.projectYearDataDAO.insert(entity);
        return CommonResultEnum.SUCCESS;
    }

    @Override
    public ServiceResult update(ProjectYearDataDTO dto) {
        String id = dto.getId();
        if (StringUtils.isEmpty(id)) {
            return CommonResultEnum.NOT_EXIST;
        }
        ProjectYearData entity = this.projectYearDataDAO.selectById(id);
        if (entity == null) {
            return CommonResultEnum.NOT_EXIST;
        }
        // TODO 添加其他校验逻辑，如数据权限

        entity.setProjectId(dto.getProjectId());
        entity.setBatchId(dto.getBatchId());
        entity.setProductionRate(dto.getProductionRate());
        entity.setWaterInjection(dto.getWaterInjection());
        entity.setSteamInjection(dto.getSteamInjection());
        entity.setLiquidOutput(dto.getLiquidOutput());
        entity.setOilOutput(dto.getOilOutput());
        entity.setGasOutput(dto.getGasOutput());
        entity.setCondensateOutput(dto.getCondensateOutput());
        entity.setLiquidGasOutput(dto.getLiquidGasOutput());
        entity.setDrugCost(dto.getDrugCost());
        this.projectYearDataDAO.updateById(entity);
        return CommonResultEnum.SUCCESS;
    }

    @Override
    public ServiceResult deleteById(String id) {
        // TODO 添加校验逻辑，如数据权限
        this.projectYearDataDAO.deleteById(id);
        return CommonResultEnum.SUCCESS;
    }

    @Override
    public ServiceResult importExcelData(String batchId,
                                         List<ProjectYearDataDTO> excelOriDataList) {
        if(StringUtils.isBlank(batchId)){
            return CommonResultEnum.VALUE_LOOSE;
        }
        //DONE：删除重复项目值、删除projectMap中不存在的值

        LambdaQueryWrapper<ProjectYearData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectYearData::getBatchId,batchId);
        final String userId = getUserId();
        projectYearDataDAO.delete(queryWrapper);
        List<ProjectYearData> projectYearDataList = new ArrayList<>();
        //DONE：数据转换并存储
        for (ProjectYearDataDTO dto : excelOriDataList) {
            final ProjectYearData yearData = parseDTO2Entity(dto);
            yearData.setBatchId(batchId);
            yearData.setCreateUser(userId);
            yearData.setCreateTime(new Date());
            yearData.setId(IdGen.uuid());
            if (yearData.getCostRatio() == null) {
                yearData.setCostRatio(DEFAULT_RATIO);
            }
           if (yearData.getInvestRatio() == null) {
               yearData.setInvestRatio(DEFAULT_RATIO);
           }
           if (yearData.getOutputRatio() == null) {
               yearData.setOutputRatio(DEFAULT_RATIO);
           }
            projectYearDataList.add(yearData);
        }
        int i = this.saveBatch(projectYearDataList, projectYearDataDAO, 200);
        return CommonResultEnum.SUCCESS;
    }

    @Override
    public List<ProjectYearDataExcelDTO> getExcelData(String batchId) {
        LambdaQueryWrapper<ProjectInfo> queryProjectWrapper = new LambdaQueryWrapper();
        queryProjectWrapper.eq(ProjectInfo::getBatchId,batchId);
        List<ProjectInfo> projectInfoList = projectInfoDAO.selectList(queryProjectWrapper);
        if(projectInfoList == null || projectInfoList.isEmpty()){
            return Collections.emptyList();
        }
        ProjectYearDataDTO dto = new ProjectYearDataDTO();
        dto.setPageSize(PageDTO.ALL);
        dto.setBatchId(batchId);
        List<ProjectYearData> projectYearList = projectYearDataDAO.queryList(dto);
        if(projectYearList == null || projectYearList.isEmpty()){
            return Collections.emptyList();
        }

        Map<String,String> projectMap = new HashMap<>();
        for (ProjectInfo entity : projectInfoList) {
            projectMap.put(entity.getId(),entity.getName());
        }

        List<String> itemTypeList = new ArrayList<>();
        itemTypeList.add("生产时率（%）");
        itemTypeList.add("注水量（万方）");
        itemTypeList.add("注蒸汽量（万吨）");
        itemTypeList.add("产液量（万吨）");
        itemTypeList.add("原油产量（万吨）");
        itemTypeList.add("天然气产量（亿方）");
        itemTypeList.add("轻烃产量（万吨）");
        itemTypeList.add("液化气产量（万吨）");
        itemTypeList.add("药剂费（万元）");

        List<ProjectYearDataExcelDTO> resultList = new ArrayList<>();
        for (Map.Entry<String,String> entry : projectMap.entrySet()) {
            String projectId = entry.getKey();
            String projectName = entry.getValue();

            List<ProjectYearData> dataList = projectYearList.stream().filter(
                    item -> item.getProjectId().equals(projectId)).collect(Collectors.toList());
            if(dataList == null || dataList.isEmpty()){
                continue;
            }
            Map<Integer,ProjectYearData> yearDataMap = new HashMap<>();
            for (ProjectYearData projectYearData : dataList) {
                yearDataMap.put(projectYearData.getYear(),projectYearData);
            }
            for (String itemType : itemTypeList) {
                ProjectYearDataExcelDTO excelDTO = new ProjectYearDataExcelDTO();
                excelDTO.setProjectName(projectName);
                excelDTO.setItemType(itemType);
                for (int i = 1; i < 21; i++) {

                    String value = this.getExcelValue(itemType,yearDataMap.get(i));
                    if( i == 1){
                        excelDTO.setFirstYear(value);
                    }else if(i == 2){
                        excelDTO.setSecondYear(value);
                    }else if(i == 3){
                        excelDTO.setThirdYear(value);
                    }else if(i == 4){
                        excelDTO.setFourthYear(value);
                    }else if(i == 5){
                        excelDTO.setFifthYear(value);
                    }else if(i == 6){
                        excelDTO.setSixthYear(value);
                    }else if(i == 7){
                        excelDTO.setSeventhYear(value);
                    }else if(i == 8){
                        excelDTO.setEighthYear(value);
                    }else if(i == 9){
                        excelDTO.setNinthYear(value);
                    }else if(i == 10){
                        excelDTO.setTenthYear(value);
                    }else if(i == 11){
                        excelDTO.setEleventhYear(value);
                    }else if(i == 12){
                        excelDTO.setTwelfthYear(value);
                    }else if(i == 13){
                        excelDTO.setThirteenthYear(value);
                    }else if(i == 14){
                        excelDTO.setFourteenthYear(value);
                    }else if(i == 15){
                        excelDTO.setFifteenthYear(value);
                    }else if(i == 16){
                        excelDTO.setSixteenthYear(value);
                    }else if(i == 17){
                        excelDTO.setSeventeenthYear(value);
                    }else if(i == 18){
                        excelDTO.setEighteenthYear(value);
                    }else if(i == 19){
                        excelDTO.setNineteenthYear(value);
                    }else if(i == 20){
                        excelDTO.setTwentiethYear(value);
                    }
                }
                resultList.add(excelDTO);
            }
        }

        return resultList;
    }

    /**
     * 获取项目的调整系数
     * @param projectIds
     * @return key 参数类型 value 参数数组
     */
    @Override
    public Map<String,List<Map<String,String>>> queryRatioByProjectIds(Set<String> projectIds) {
        Map<String,List<Map<String,String>>> dataMap = new HashMap<>();

        dataMap.put(AdjustRatioEnum.COST_RATIO.getId(), Lists.newArrayList());
        dataMap.put(AdjustRatioEnum.INVEST_RATIO.getId(), Lists.newArrayList());
        dataMap.put(AdjustRatioEnum.OUTPUT_RATIO.getId(), Lists.newArrayList());
        if (CollectionUtils.isEmpty(projectIds)) {
            return dataMap;
        }
        final ProjectYearDataDTO dto = new ProjectYearDataDTO();
        dto.setProjectIdList(projectIds);
        final List<ProjectYearData> dataList = projectYearDataDAO.queryList(dto);
        if (CollectionUtils.isEmpty(dataList)){
            return dataMap;
        }
        final ProjectInfoDTO infoDTO = new ProjectInfoDTO();
        infoDTO.setIdList(projectIds);
        final List<ProjectInfo> projectInfos = projectInfoDAO.queryList(infoDTO);
        if (CollectionUtils.isEmpty(projectInfos)) {
            throw new ServiceException("项目不存在","项目不存在",null);
        }
        final Map<String, List<ProjectYearData>> listMap = dataList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(ProjectYearData::getProjectId));
        for (ProjectInfo projectInfo : projectInfos) {
            Map<String,String> costMap= new HashMap<>();
            Map<String,String> investMap= new HashMap<>();
            Map<String,String> outputMap= new HashMap<>();
            costMap.put(YEAR_STR,projectInfo.getYear().toString());
            investMap.put(YEAR_STR,projectInfo.getYear().toString());
            outputMap.put(YEAR_STR,projectInfo.getYear().toString());

            costMap.put("projectId",projectInfo.getId());
            investMap.put("projectId",projectInfo.getId());
            outputMap.put("projectId",projectInfo.getId());

            costMap.put("name",projectInfo.getName());
            investMap.put("name",projectInfo.getName());
            outputMap.put("name",projectInfo.getName());

            costMap.put("buildOffice",projectInfo.getBuildOffice());
            investMap.put("buildOffice",projectInfo.getBuildOffice());
            outputMap.put("buildOffice",projectInfo.getBuildOffice());

            costMap.put("evaluationPeriod",projectInfo.getEvaluationPeriod().toString());
            investMap.put("evaluationPeriod",projectInfo.getEvaluationPeriod().toString());
            outputMap.put("evaluationPeriod",projectInfo.getEvaluationPeriod().toString());

            final List<ProjectYearData> projectYearDatas = listMap.get(projectInfo.getId());
            if (CollectionUtils.isEmpty(projectYearDatas)) {
                continue;
            }
            for (ProjectYearData projectYearData : projectYearDatas) {
                Double costRatio = projectYearData.getCostRatio();
                if (costRatio == null) {
                    costRatio = 1D;
                }
                costMap.put(YEAR_STR + projectYearData.getYear(), costRatio.toString());
                Double investRatio = projectYearData.getInvestRatio();
                if (investRatio == null) {
                    investRatio = 1D;
                }
                investMap.put(YEAR_STR + projectYearData.getYear(), investRatio.toString());
                Double outputRatio = projectYearData.getOutputRatio();
                if (outputRatio == null) {
                    outputRatio = 1D;
                }
                outputMap.put(YEAR_STR + projectYearData.getYear(), outputRatio.toString());
            }
            dataMap.get(AdjustRatioEnum.COST_RATIO.getId()).add(costMap);
            dataMap.get(AdjustRatioEnum.INVEST_RATIO.getId()).add(investMap);
            dataMap.get(AdjustRatioEnum.OUTPUT_RATIO.getId()).add(outputMap);

        }

        return dataMap;
    }

    @Override
    public ServiceResult saveRatio(List<ProjectYearDataDTO> dtos) {
        if (CollectionUtils.isEmpty(dtos)) {
            throw new ServiceException("保存参数为空","保存参数为空",null);
        }
        // 获取所有项目ID
        final Set<String> projectIdList = dtos.stream()
                .filter(Objects::nonNull)
                .map(ProjectYearDataDTO::getProjectId)
                .distinct()
                .collect(Collectors.toSet());
        // dto 构造为map，减少循环查询数据库
        final Map<String, Map<Integer, ProjectYearDataDTO>> map = dtos.stream().collect(
                Collectors.groupingBy(
                        ProjectYearDataDTO::getProjectId,
                        Collectors.toMap(ProjectYearDataDTO::getYear, Function.identity(), (v1, v2) -> v1)));
        final ProjectYearDataDTO dto = new ProjectYearDataDTO();
        dto.setProjectIdList(projectIdList);
        final List<ProjectYearData> projectYearDataList = projectYearDataDAO.queryList(dto);
        if (CollectionUtils.isEmpty(projectYearDataList)) {
            throw new ServiceException("未找到对应的年份数据","未找到对应的年份数据",null);
        }
        for (ProjectYearData yearData : projectYearDataList) {
            if (Objects.isNull(yearData)) {
                continue;
            }
            final Map<Integer, ProjectYearDataDTO> dataDTOMap = map.get(yearData.getProjectId());
            if (MapUtils.isEmpty(dataDTOMap)) {
                continue;
            }
            final ProjectYearDataDTO projectYearDataDTO = dataDTOMap.get(yearData.getYear());
            if (Objects.isNull(projectYearDataDTO)) {
                continue;
            }
            yearData.setCostRatio(projectYearDataDTO.getCostRatio());
            yearData.setOutputRatio(projectYearDataDTO.getOutputRatio());
            yearData.setInvestRatio(projectYearDataDTO.getInvestRatio());
        }
        updateBatchById(projectYearDataList,projectYearDataDAO,ProjectYearData.class);
        return  CommonResultEnum.SUCCESS;
    }

    private String getExcelValue(String itemType, ProjectYearData projectYearData) {
        String value = "";
        if(itemType.equals("生产时率（%）")){
            value = projectYearData.getProductionRate() == null ? "" : projectYearData.getProductionRate().toString();
        }else if(itemType.equals("注水量（万方）")){
            value = projectYearData.getWaterInjection() == null ? "" : projectYearData.getWaterInjection().toString();
        }else if(itemType.equals("注蒸汽量（万吨）")){
            value = projectYearData.getSteamInjection() == null ? "" : projectYearData.getSteamInjection().toString();
        }else if(itemType.equals("产液量（万吨）")){
            value = projectYearData.getLiquidOutput() == null ? "" : projectYearData.getLiquidOutput().toString();
        }else if(itemType.equals("原油产量（万吨）")){
            value = projectYearData.getOilOutput() == null ? "" : projectYearData.getOilOutput().toString();
        }else if(itemType.equals("天然气产量（亿方）")){
            value = projectYearData.getGasOutput() == null ? "" : projectYearData.getGasOutput().toString();
        }else if(itemType.equals("轻烃产量（万吨）")){
            value = projectYearData.getCondensateOutput() == null ? "" : projectYearData.getCondensateOutput().toString();
        }else if(itemType.equals("液化气产量（万吨）")){
            value = projectYearData.getLiquidGasOutput() == null ? "" : projectYearData.getLiquidGasOutput().toString();
        }else if(itemType.equals("药剂费（万元）")){
            value = projectYearData.getDrugCost() == null ? "" : projectYearData.getDrugCost().toString();
        }
        return value;
    }

}
